﻿namespace Algo.Sort
{
    using System.Collections.Generic;

    internal sealed class CocktailSortStrategy : ISortStrategy
    {
        public IEnumerable<T> Sort<T>(IEnumerable<T> items, IComparer<T> comparer, IAlgoExtensions extensions)
        {
            var iterationsCount = 0;
            var list = SortUtilities.CopyToList(items);
            if (list.Count <= 1)
            {
                return list;
            }

            var count = list.Count / 2;
            try
            {
                for (var i = 0; i < count; i++)
                {
                    var beg = 0;
                    var end = list.Count - 1;

                    do
                    {
                        if (SortUtilities.IsGreaterThen(comparer, list[beg], list[beg + 1]))
                        {
                            SortUtilities.Swap(list, beg, beg + 1);
                        }
                        
                        beg++;

                        if (SortUtilities.IsGreaterThen(comparer, list[end - 1], list[end]))
                        {
                            SortUtilities.Swap(list, end - 1, end);
                        }

                        end--;
                        
                        iterationsCount++;
                    }
                    while (beg <= end);
                }
            }
            finally
            {
                IMetricsExtension metricsBehaviour;
                if (extensions.TryGet(out metricsBehaviour))
                {
                    metricsBehaviour.RegisterIterations(iterationsCount);
                }
            }

            return list;
        }
    }
}
